package com.lm56.common;


import org.apache.commons.codec.DecoderException;
import org.apache.commons.codec.binary.Hex;
import org.apache.commons.lang3.Validate;
import org.springframework.security.authentication.encoding.MessageDigestPasswordEncoder;

import java.security.GeneralSecurityException;
import java.security.MessageDigest;
import java.security.SecureRandom;

/**
 * Created by k_way on 2016/6/6.
 */
public class MyMd5PasswordEncoder extends MessageDigestPasswordEncoder {

    private static final int HASH_INTERATIONS = 1024;
    private static final int SALT_SIZE = 8;

    private static SecureRandom random = new SecureRandom();

    public static String genSalt() {
        Validate.isTrue(SALT_SIZE > 0, "numBytes argument must be a positive integer (1 or larger)", (long) SALT_SIZE);
        byte[] bytes = new byte[SALT_SIZE];
        random.nextBytes(bytes);
        return Hex.encodeHexString(bytes);
    }

    public MyMd5PasswordEncoder() {
        super("MD5");
    }

    @Override
    public String encodePassword(String rawPass, Object salt) {
        if (salt == null) {
            salt = "";
        }


        String saltStr = (String) salt;
        try {
            byte[] tmpSalt = Hex.decodeHex(saltStr.toCharArray());
            byte[] hashPassword = digest(rawPass.getBytes(), "SHA-1", tmpSalt, HASH_INTERATIONS);
            return Hex.encodeHexString(hashPassword);
        } catch (DecoderException e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        }

    }

    @Override
    public boolean isPasswordValid(String encPass, String rawPass, Object salt) {
        String tmpPass = encodePassword(rawPass, salt);
        return tmpPass.compareTo(encPass) == 0 ? true : false;
    }


    private static byte[] digest(byte[] input, String algorithm, byte[] salt, int iterations) {
        try {
            MessageDigest e = MessageDigest.getInstance(algorithm);
            if (salt != null) {
                e.update(salt);
            }

            byte[] result = e.digest(input);

            for (int i = 1; i < iterations; ++i) {
                e.reset();
                result = e.digest(result);
            }

            return result;
        } catch (GeneralSecurityException ex) {
            throw new RuntimeException(ex);
        }
    }
}
